package com.rsk.datasource.sharding;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import javax.sql.DataSource;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

import com.alibaba.druid.filter.Filter;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.rsk.datasource.sharding.rules.MasterSlaveRules;
import com.rsk.datasource.sharding.rules.SysUserRules;
import com.rsk.datasource.sharding.rules.SysUserRules1;

import io.shardingjdbc.core.api.MasterSlaveDataSourceFactory;
import io.shardingjdbc.core.api.ShardingDataSourceFactory;
import io.shardingjdbc.core.api.algorithm.masterslave.MasterSlaveLoadBalanceAlgorithmType;
import io.shardingjdbc.core.api.config.MasterSlaveRuleConfiguration;
import io.shardingjdbc.core.api.config.ShardingRuleConfiguration;
import io.shardingjdbc.core.rule.MasterSlaveRule;

@Configuration
public class ShardingConfig {
	
	public static final String basePackage ="spring.datasource.";
	
	/**
	 * shardingjdbc数据源
	 * @return
	 * @throws SQLException
	 */
	@Bean
    public DataSource dataSource(Environment env) throws SQLException{
		// 配置真实数据源
	    /*Map<String, DataSource> dataSourceMap = new HashMap<>();
	    DruidDataSource dba1 = createDba1(env);
	    dataSourceMap.put("ds0", dba1);
	    DruidDataSource dba2 = createDba2(env);
	    dataSourceMap.put("ds1", dba2);
	    DruidDataSource dba3 = createDba3(env);
	    dataSourceMap.put("ds2", dba3);
	    DruidDataSource dba4 = createDba4(env);
	    dataSourceMap.put("ds3", dba4);*/
		Map<String, DataSource> dataSourceMap = new HashMap<>();
		DruidDataSource ms1 = createDba1(env);
		/*DruidDataSource ms2 = createDba2(env);
		DruidDataSource sl1 = createDba3(env);
		DruidDataSource sl2 = createDba4(env);*/
		dataSourceMap.put("ms1", ms1);
		/*dataSourceMap.put("ms2", ms2);
		dataSourceMap.put("sl1", sl1);
		dataSourceMap.put("sl2", sl2);*/
	     
	    // 配置分片规则
	    ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
	   // shardingRuleConfig.getTableRuleConfigs().add(SysUserRules1.sysUsersRulesConfig());
	    //shardingRuleConfig.getTableRuleConfigs().add(addressRuleConfig());
	    //shardingRuleConfig.getMasterSlaveRuleConfigs().add(MasterSlaveRules.masterSlaveRulesConfig());
	    Properties p = new Properties();
	    p.setProperty("sql.show",Boolean.TRUE.toString());
	    // 获取数据源对象
	    DataSource dataSource = ShardingDataSourceFactory.createDataSource(dataSourceMap, shardingRuleConfig, new ConcurrentHashMap<String,Object>(), p);
	    return dataSource;
	}

	/**
	 * dba1
	 * @return
	 * @throws SQLException 
	 */
	private DruidDataSource createDba1(Environment env) throws SQLException {
         String dba = "dba1"+".";
		// 配置dba1数据源 
	    DruidDataSource dataSource = new DruidDataSource();
	    dataSource.setDriverClassName(env.getProperty(basePackage+dba+"driverClassName"));
	    dataSource.setUrl(env.getProperty(basePackage+dba+"url"));
	    dataSource.setUsername(env.getProperty(basePackage+dba+"username"));
	    dataSource.setPassword(env.getProperty(basePackage+dba+"password"));
	    // 每个分区最大的连接数
	    dataSource.setMaxActive(Integer.valueOf(env.getProperty(basePackage+dba+"maxActive")));
	    // 每个分区最小的连接数
	    dataSource.setMinIdle(Integer.valueOf(env.getProperty(basePackage+dba+"minIdle")));
	    dataSource.setProxyFilters(Lists.newArrayList(statFilter()));
	    dataSource.setFilters("stat, wall");
		return dataSource;
	}
	/**
	 * dba2
	 * @return
	 * @throws SQLException 
	 */
	private DruidDataSource createDba2(Environment env) throws SQLException {
		String dba = "dba2"+".";
		// 配置dba1数据源
		DruidDataSource dataSource = new DruidDataSource();
		dataSource.setDriverClassName(env.getProperty(basePackage+dba+"driverClassName"));
	    dataSource.setUrl(env.getProperty(basePackage+dba+"url"));
	    dataSource.setUsername(env.getProperty(basePackage+dba+"username"));
	    dataSource.setPassword(env.getProperty(basePackage+dba+"password"));
		// 每个分区最大的连接数
		dataSource.setMaxActive(Integer.valueOf(env.getProperty(basePackage+dba+"maxActive")));
		// 每个分区最小的连接数
		dataSource.setMinIdle(Integer.valueOf(env.getProperty(basePackage+dba+"minIdle")));
		dataSource.setProxyFilters(Lists.newArrayList(statFilter()));
		dataSource.setFilters("stat,wall,slf4j");
		return dataSource;
	}
	
	/**
	 * dba3
	 * @return
	 * @throws SQLException 
	 */
	private DruidDataSource createDba3(Environment env) throws SQLException {
		String dba = "dba3"+".";
		// 配置dba1数据源
		DruidDataSource dataSource = new DruidDataSource();
		dataSource.setDriverClassName(env.getProperty(basePackage+dba+"driverClassName"));
	    dataSource.setUrl(env.getProperty(basePackage+dba+"url"));
	    dataSource.setUsername(env.getProperty(basePackage+dba+"username"));
	    dataSource.setPassword(env.getProperty(basePackage+dba+"password"));
		// 每个分区最大的连接数
		dataSource.setMaxActive(Integer.valueOf(env.getProperty(basePackage+dba+"maxActive")));
		// 每个分区最小的连接数
		dataSource.setMinIdle(Integer.valueOf(env.getProperty(basePackage+dba+"minIdle")));
		dataSource.setProxyFilters(Lists.newArrayList(statFilter()));
		dataSource.setFilters("stat,wall,slf4j");
		return dataSource;
	}
	/**
	 * dba4
	 * @return
	 * @throws SQLException 
	 */
	private DruidDataSource createDba4(Environment env) throws SQLException {
		String dba = "dba4"+".";
		// 配置dba1数据源
		DruidDataSource dataSource = new DruidDataSource();
		dataSource.setDriverClassName(env.getProperty(basePackage+dba+"driverClassName"));
	    dataSource.setUrl(env.getProperty(basePackage+dba+"url"));
	    dataSource.setUsername(env.getProperty(basePackage+dba+"username"));
	    dataSource.setPassword(env.getProperty(basePackage+dba+"password"));
		// 每个分区最大的连接数
		dataSource.setMaxActive(Integer.valueOf(env.getProperty(basePackage+dba+"maxActive")));
		// 每个分区最小的连接数
		dataSource.setMinIdle(Integer.valueOf(env.getProperty(basePackage+dba+"minIdle")));
		dataSource.setProxyFilters(Lists.newArrayList(statFilter()));
		dataSource.setFilters("stat,wall,slf4j");
		return dataSource;
	}

	
	
	
	@Bean
	public Filter statFilter(){
	    	StatFilter filter = new StatFilter();
	    	filter.setSlowSqlMillis(5000);
	    	filter.setLogSlowSql(true);
	    	filter.setMergeSql(true);
	    	return filter;
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Bean
    public ServletRegistrationBean druidServlet() {
        //logger.info("init Druid Servlet Configuration ");
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
        servletRegistrationBean.setServlet(new StatViewServlet());
        servletRegistrationBean.addUrlMappings("/druid/*");
        Map<String, String> initParameters = new HashMap<>();
        initParameters.put("loginUsername", "123");// 用户名
        initParameters.put("loginPassword", "123");// 密码
        initParameters.put("resetEnable", "false");// 禁用HTML页面上的“Reset All”功能
        initParameters.put("allow", ""); // IP白名单 (没有配置或者为空，则允许所有访问)
        initParameters.put("deny", "192.168.20.38");// IP黑名单 (存在共同时，deny优先于allow)
        servletRegistrationBean.setInitParameters(initParameters);
        return servletRegistrationBean;
    }


    @SuppressWarnings({ "rawtypes", "unchecked" })
	@Bean
    public FilterRegistrationBean druidWebStatViewFilter() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean(new WebStatFilter());
        registrationBean.addInitParameter("urlPatterns", "/*");
        registrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*");
        return registrationBean;
    }
    
}
